package com.am.server.api.system.permission.service.impl;

import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpUtil;
import com.am.server.api.system.permission.config.model.Menu;
import com.am.server.api.system.permission.model.enumerate.MenuType;
import com.am.server.api.system.permission.service.PermissionService;
import com.am.server.api.system.permission.service.UserPermissionCacheService;
import com.am.server.api.system.role.model.entity.RoleEntity;
import com.am.server.api.system.user.dao.cache.UserPermissionCacheDao;
import com.am.server.api.system.user.dao.rdb.AdminUserDao;
import com.am.server.api.system.user.model.entity.AdminUserEntity;
import com.am.server.api.system.user.model.entity.UserPermissionCacheEntity;
import com.am.server.common.util.tree.TreeUtils;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * redis用户权限缓存实现
 *
 * @author 阮雪峰
 */
@Service
public class UserPermissionCacheServiceImpl implements UserPermissionCacheService, StpInterface {

    private final UserPermissionCacheDao userPermissionCacheDao;
    private final AdminUserDao adminUserDao;
    private final PermissionService permissionService;

    public UserPermissionCacheServiceImpl(UserPermissionCacheDao userPermissionCacheDao, AdminUserDao adminUserDao, PermissionService permissionService) {
        this.userPermissionCacheDao = userPermissionCacheDao;
        this.adminUserDao = adminUserDao;
        this.permissionService = permissionService;
    }

    @Override
    public void set(Long uid, List<Menu> permissions, List<String> permissionKeyList) {
        userPermissionCacheDao.save(new UserPermissionCacheEntity(uid, permissions, permissionKeyList));
    }

    @Override
    public List<Menu> saveOrGet(Long uid) {
        return Optional.ofNullable(userPermissionCacheDao.findById(uid))
                .map(UserPermissionCacheEntity::getPermissionList)
                .orElseGet(() -> save(uid).getPermissionList());
    }

    @Override
    public Optional<UserPermissionCacheEntity> get(Long uid) {
        return Optional.ofNullable(userPermissionCacheDao.findById(uid));
    }

    @Override
    public void remove(Long uid) {
        userPermissionCacheDao.remove(uid);
    }

    @Override
    public void removeAll() {
        userPermissionCacheDao.removeAll();
    }

    @Override
    public void removeAll(Long... ids) {
        userPermissionCacheDao.removeAll(ids);
    }

    @Override
    public List<String> getPermissionList(Object loginId, String loginKey) {
        return userPermissionCacheDao.getPermissionKey(StpUtil.getLoginIdAsLong());
    }

    @Override
    public void refresh(Long uid) {
        save(uid);
    }

    private UserPermissionCacheEntity save(Long uid) {
        Set<String> permissions = new HashSet<>();
        List<RoleEntity> roleList = adminUserDao.findById(uid).map(AdminUserEntity::getRoles).orElse(new ArrayList<>());

        roleList.stream().map(RoleEntity::getPermissions).forEach(permissions::addAll);

        List<Menu> menuList = permissionService.findByIds(permissions);
        UserPermissionCacheEntity userPermissionCacheEntity = new UserPermissionCacheEntity(
                uid,
                TreeUtils.build(menuList.stream().filter(item -> !item.getType().equals(MenuType.ACTION)).toList()),
                menuList.stream().filter(item -> item.getKey() != null && !item.getKey().isEmpty()).map(Menu::getKey).flatMap(Collection::stream).distinct().toList()
        );
        userPermissionCacheDao.save(userPermissionCacheEntity);
        return userPermissionCacheEntity;
    }

    @Override
    public List<String> getRoleList(Object loginId, String loginKey) {
        return new ArrayList<>(0);
    }
}
